package com.example.md.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;

import com.example.md.dto.file.FileTreeResDTO.TreeNode;

@Service
public class FileService {
    /**
     * 以 dirPath + basePath 为根节点，获取文件树
     * @param dirPath
     * @param basePath
     * @return
     */
    public TreeNode createTree(String dirPath, String basePath) throws IOException {
        Path path = Paths.get(dirPath);
        TreeNode node = new TreeNode(path.getFileName().toString(), 
                                    basePath.isEmpty() ? path.getFileName().toString() : basePath,
                                    true, 
                                    new ArrayList<>());

        // List<Path> entries = Files.list(path).collect(Collectors.toList());
        // 获取并排序条目
        List<Path> entries = Files.list(path)
                .sorted(Comparator.comparing(p -> p.getFileName().toString().toLowerCase()))
                .collect(Collectors.toList());

        for (Path entry : entries) {
            String relativePath = basePath.isEmpty() 
                ? entry.getFileName().toString() 
                : basePath + File.separator + entry.getFileName().toString();

            if (Files.isDirectory(entry)) {
                TreeNode childNode = createTree(entry.toString(), relativePath);
                node.getChildren().add(childNode);
            } else if (Files.isRegularFile(entry) && entry.getFileName().toString().endsWith(".md")) {
                node.getChildren().add(new TreeNode(
                    entry.getFileName().toString(),
                    relativePath,
                    false,
                    null
                ));
            }
        }

        // 对当前节点的子节点进行排序，先排目录再排文件，然后按名称排序
        Comparator<TreeNode> complexComparator = Comparator
                .comparing((TreeNode tmp) -> !tmp.getIsDirectory()) // 目录在前
                .thenComparing(TreeNode::getName, String.CASE_INSENSITIVE_ORDER);

        node.getChildren().sort(complexComparator);
        // node.getChildren().sort(Comparator.comparing(TreeNode::getName, String.CASE_INSENSITIVE_ORDER));

        return node;
    }

    
    @Value("${md_dir}")
    public String markdownDir;

    public Path validatePath(String path) {
        if (Paths.get(path).isAbsolute()) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Absolute path is not allowed");
        }

        Path fullPath = Paths.get(markdownDir, path).normalize();
        if (!fullPath.startsWith(markdownDir)) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Path traversal attempt detected");
        }

        return fullPath;
    }

    
    public void zipFolder(String folderPath, String zipFilePath) {
        try (FileOutputStream fos = new FileOutputStream(zipFilePath);
            ZipOutputStream zos = new ZipOutputStream(fos)) {

            File folder = new File(folderPath);
            zipFile(folder, "", zos);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void zipFile(File file, String basePath, ZipOutputStream zos) throws IOException {
        if (file.isDirectory()) {
            for (File subFile : file.listFiles()) {
                String newBasePath = basePath.isEmpty() 
                    ? file.getName() 
                    : basePath + File.separator + file.getName();
                zipFile(subFile, newBasePath, zos);
            }
        } else {
            try (FileInputStream fis = new FileInputStream(file)) {
                String entryName = basePath + File.separator + file.getName();
                if (basePath.isEmpty()) {
                    entryName = file.getName();
                }
                ZipEntry zipEntry = new ZipEntry(entryName);
                zos.putNextEntry(zipEntry);
                byte[] buffer = new byte[1024];
                int length;
                while ((length = fis.read(buffer))!= -1) {
                    zos.write(buffer, 0, length);
                }
                zos.closeEntry();
            }
        }
    }
}
